package com.example.ota_ble.ble.dataWrite

import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.compose.ui.geometry.Size
import androidx.core.graphics.drawable.toIcon

import com.example.ota_ble.ble.component.ota_lock
import com.example.ota_ble.ble.connect.buletoothGattManage
import com.example.ota_ble.ble.ota.ble.ota_ble_manager
import com.example.ota_ble.ble.ota.ble.ota_mcu_manager
import com.example.ota_ble.ble.ota.mcu.OPCODE_DEU
import com.example.ota_ble.crc.CRC32
import com.example.ota_ble.globbal_calss
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import java.io.BufferedInputStream
import java.io.FileInputStream
import java.io.InputStream
import java.lang.Integer.toHexString
import java.lang.Thread.sleep

@SuppressLint("MissingPermission")
class ble_write_thread(context: Context) {
    var TAG = "rocjan.ble_write_thread"
    lateinit var  bluetoothGattMg:  buletoothGattManage
    var  rtuSize: Int = 16
    var  ccontext = context

    var  paga_idx: Int = 0

    var  send_data_total_szie: Int = 0
    lateinit var uri: Uri

        // 蓝牙芯片
     fun run() {
        val contentResolver: ContentResolver = ccontext.contentResolver
        var inputStream: FileInputStream = contentResolver.openInputStream(uri) as FileInputStream
        var offset_read_size = 0
        var readsize: Int

        // 预处理
        var head: ByteArray = ByteArray(32)
        if (inputStream.read(head) == -1) {
            Log.e(TAG, "读取文件出错")
            return
        }
        send_data_total_szie =
            (head[0x18].toInt() and 0xFF) or  // head[0x18] 为最低字节
                    ((head[0x19].toInt() and 0xFF) shl 8) or  // head[0x19]
                    ((head[0x1a].toInt() and 0xFF) shl 16) or  // head[0x1a]
                    ((head[0x1b].toInt() and 0xFF) shl 24)    // head[0x1b] 为最高字节
        inputStream.close()
        inputStream = contentResolver.openInputStream(uri) as FileInputStream

        // 继续处理其他逻辑（如读取固件数据等）
        var readChunk: ByteArray = ByteArray(rtuSize)

        // 协程操作
        CoroutineScope(Dispatchers.IO).launch {
            //启动OTA
            var ack: Int
            var state_page = ByteArray(20)
            var crc32: ByteArray = ByteArray(16,{0xff.toByte()})
            ota_ble_manager.send_ble_start_page(state_page,rtuSize,false)
            // 发送开始信号
            Log.i(TAG, state_page.joinToString(", ") { "0x${it.toUByte().toString(16).padStart(2, '0')}" })
            show_down_data("start updata ble")
            send_data_to_ble(state_page)
            //数据处理
            while(inputStream.read(readChunk).also { readsize = it }!=-1)
            {

                if(readsize<rtuSize)
                {
                    crc32[0] = readChunk[readsize - 4]
                    crc32[1] = readChunk[readsize - 3]
                    crc32[2] = readChunk[readsize - 2]
                    crc32[3] = readChunk[readsize - 1]
                    if(readsize==4)
                    {
                        break
                    }
                    var chanSize =  if (readsize%16 != 0)  (readsize/16 +1) * 16  else  readsize
                    readChunk = readChunk.copyOf(chanSize)
                    readChunk.fill(0xff.toByte(),readsize,chanSize)
                }
                wait_ble_response(ota_lock.channel)
                //更新crc32
                ota_ble_manager.crc32.update(readChunk)

                var sendChunk: ByteArray = ByteArray(readChunk.size+4)
                ota_ble_manager.set_ble_format(sendChunk,readChunk,paga_idx)
                offset_read_size += readsize
                paga_idx++
                show_down_data("downloading:idx${paga_idx}，length${readsize}，" +
                        "process:${String.format("%.2f", (offset_read_size.toDouble() / send_data_total_szie.toDouble()) * 100)}%")



                send_data_to_ble(sendChunk)


                Log.i(TAG, sendChunk.joinToString(", ") { "0x${it.toUByte().toString(16).padStart(2, '0')}" })


            }

            //结束校验包

            var end_page = ByteArray(22)
            ota_ble_manager.send_ble_end_page(end_page,paga_idx-1)
            // 发送结束信号
            Log.i(TAG, end_page.joinToString(", ") { "0x${it.toUByte().toString(16).padStart(2, '0')}" })
            wait_ble_response(ota_lock.channel)
            send_data_to_ble(end_page)
            show_down_data("end updata ble")
        }



    }
    fun run_mcu_ota() {
        val contentResolver: ContentResolver = ccontext.contentResolver
        var inputStream: FileInputStream = contentResolver.openInputStream(uri) as FileInputStream
        var Protof_size = if(((this.rtuSize - 3 - 7 ) % 16)==0) (this.rtuSize - 3 - 7 ).toInt() else (((this.rtuSize - 3 - 7 )/16)*16).toInt()
        var readBlock: ByteArray = ByteArray(Protof_size - 7)
        var readsize : Int
        var offset_read_size = 0
        Log.i(TAG,"Protof_size = ${Protof_size}")

        CoroutineScope(Dispatchers.IO).launch {
            var file_size = inputStream.available().toLong()
            var crc32_check = get_file_crc32(inputStream)
            var start_addr  = 0
            inputStream = contentResolver.openInputStream(uri) as FileInputStream

//            // 进入OTA模式
//            send_inquiry(0x00)
//            sleep(100)
//            send_boot()
//            sleep(100)
//            send_reset()
//            sleep(100)
//            send_earse(0,10)
//            sleep(100)
//            send_verify(0,10,0x11223344)
//            // 使mcu进入升级状态
//            sleep(100)
            // 等待mcu重启到准备接受状态

            // 写入数据
            while(inputStream.read(readBlock).also { readsize = it }!=-1)
            {
                readBlock = readBlock.copyOf(readsize)
                show_down_data("downloading:idx${start_addr}，length${readsize}，" +
                        "process:${String.format("%.2f", (start_addr.toDouble() / file_size.toDouble()) * 100)}%")
                send_updata_data(start_addr,readsize,readBlock)
                start_addr += readsize
                sleep(100)
            }




        }



    }
    private  suspend  fun get_file_crc32(inputStream: FileInputStream): Int
    {
        var buffer = ByteArray(1024) // 缓冲区大小，适应文件大小
        var init_crc = 0
        try {
            // 读取文件内容并进行CRC校验
            var bytesRead: Int
            while (inputStream?.read(buffer).also { bytesRead = it ?: -1 } != -1) {
                // 读取到数据后更新CRC
                init_crc = CRC32.update(init_crc, buffer.copyOfRange(0, bytesRead),buffer.size)
            }

            // 完成CRC校验后打印结果
            withContext(Dispatchers.Main) {
                Log.i(TAG,"文件的CRC值: $init_crc")
            }
            return init_crc
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            inputStream?.close()
        }
        return  init_crc
    }

     suspend fun wait_ble_response(channels : Channel<Int>) {
        val result: Int
        runBlocking {
            result = withTimeoutOrNull(3000) {  // 设置超时时间为3秒
                channels.receive()
            }!!
        }
        // 检查 result 的值
        when (result) {

            0-> {  // 假设你期望接收到的数据是0
                Log.i(TAG, "recv-rsp success")
            }
            else -> {
                (ccontext as? Activity)?.runOnUiThread {
                    val builder = AlertDialog.Builder(ccontext)
                    builder.setTitle("提示")
                        .setMessage("下载失败！！！返回和确认将返回上一页" +
                                "resson: ${if(result == null) "ble mcu rsp timeout " else "ble mcu reject"}")
                        .setPositiveButton("确定") { dialog, which ->
                            // 点击“确定”按钮后的操作
                            val activity = ccontext as? Activity
                            activity?.finish()  // 结束当前 Activity，返回上一页
                        }
                        .setNegativeButton("取消") { dialog, which ->
                            // 点击“取消”按钮后的操作
                            val activity = ccontext as? Activity
                            activity?.finish()  // 结束当前 Activity，返回上一页
                        }

                    val dialog = builder.create()
                    dialog.show()

                }
                while(true){}



            }
        }

        // 如果失败，进入死循环（仅用于调试或示范，不建议生产环境使用）
        if (result != 0) {
            while (true) {}
        }
    }







    fun send_data_to_ble(data: ByteArray)
    {
        this.bluetoothGattMg.writeDataToCharacteristic(this.bluetoothGattMg.ota_ble_characteristic,
            data)
    }

    /******************************构建控制包************************************/
    suspend fun send_inquiry(subcode:Byte)
    {
        var load:ByteArray = ByteArray(1)
        load[0] = subcode
        var pkt:ByteArray = ByteArray(8)
        ota_mcu_manager.build_send_ctrl_page(pkt,OPCODE_DEU.dfu_opcode_inquiry.toByte(),load)
        send_data_to_mcu_ctrl(pkt)
        wait_ble_response(ota_lock.ota_ctrl_lock)
    }
    suspend fun send_boot()
    {
        var load:ByteArray = ByteArray(1)
        load[0] = 1;
        var pkt:ByteArray = ByteArray(8)
        ota_mcu_manager.build_send_ctrl_page(pkt,OPCODE_DEU.dfu_opcode_boot.toByte(),load)
        send_data_to_mcu_ctrl(pkt)
        wait_ble_response(ota_lock.ota_ctrl_lock)
    }
    suspend fun send_reset()
    {
        var load:ByteArray = ByteArray(1)
        load[0] = 1;
        var pkt:ByteArray = ByteArray(8)
        ota_mcu_manager.build_send_ctrl_page(pkt,OPCODE_DEU.dfu_opcode_reset.toByte(),load)
        send_data_to_mcu_ctrl(pkt)
        wait_ble_response(ota_lock.ota_ctrl_lock)
    }
    suspend fun send_earse(address: Int,size: Int)
    {
        var load:ByteArray = ByteArray(8)
        load[0] = (address and 0xff ).toByte()
        load[1] = ((address shr 8) and 0xff ).toByte()
        load[2] = ((address shr 16) and 0xff ).toByte()
        load[3] = ((address shr 24) and 0xff ).toByte()
        load[4] = (size and 0xff ).toByte()
        load[5] = ((size shr 8) and 0xff ).toByte()
        load[6] = ((size shr 16) and 0xff ).toByte()
        load[7] = ((size shr 24) and 0xff ).toByte()
        var pkt:ByteArray = ByteArray(15)
        ota_mcu_manager.build_send_ctrl_page(pkt,OPCODE_DEU.dfu_opcode_erase.toByte(),load)
        send_data_to_mcu_ctrl(pkt)
        wait_ble_response(ota_lock.ota_ctrl_lock)
    }
    suspend fun send_verify(address: Int,size: Int,crc: Int)
    {
        var load:ByteArray = ByteArray(12)
        load[0] = (address and 0xff ).toByte()
        load[1] = ((address shr 8) and 0xff ).toByte()
        load[2] = ((address shr 16) and 0xff ).toByte()
        load[3] = ((address shr 24) and 0xff ).toByte()
        load[4] = (size and 0xff ).toByte()
        load[5] = ((size shr 8) and 0xff ).toByte()
        load[6] = ((size shr 16) and 0xff ).toByte()
        load[7] = ((size shr 24) and 0xff ).toByte()
        load[8] = (crc and 0xff ).toByte()
        load[9] = ((crc shr 8) and 0xff ).toByte()
        load[10] = ((crc shr 16) and 0xff ).toByte()
        load[11] = ((crc shr 24) and 0xff ).toByte()
        var pkt:ByteArray = ByteArray(19)
        ota_mcu_manager.build_send_ctrl_page(pkt,OPCODE_DEU.dfu_opcode_erase.toByte(),load)
        send_data_to_mcu_ctrl(pkt)
        wait_ble_response(ota_lock.ota_ctrl_lock)
    }
    /******************************构建数据包************************************/
    suspend fun send_updata_data(address: Int,size:Int,load:ByteArray)
    {
        var pkt:ByteArray = ByteArray(size.toInt() + 10)
        ota_mcu_manager.build_send_data_page(pkt,address,size,load)
        send_data_to_mcu_data(pkt)
        wait_ble_response(ota_lock.ota_data_lock)
    }
    /******************************构建控制，数据发送函数************************************/
    fun send_data_to_mcu_ctrl(data: ByteArray)
    {
        Log.i(TAG,data.joinToString(", "){"0x" + it.toUByte().toString(16).padStart(2,'0')})
        this.bluetoothGattMg.writeDataToCharacteristic(this.bluetoothGattMg.ota_mcu_characteristic_ctrl,
            data)
    }
    fun send_data_to_mcu_data(data: ByteArray)
    {
        Log.i(TAG,data.joinToString(", "){"0x" + it.toUByte().toString(16).padStart(2,'0')})
        this.bluetoothGattMg.writeDataToCharacteristic(this.bluetoothGattMg.ota_mcu_characteristic_data,
            data)
    }
    /******************************预初始化************************************/
    fun pre_init(uri:Uri,bluetoothGattMg:  buletoothGattManage, rtuSize: Int = 16)
    {
            this.bluetoothGattMg = bluetoothGattMg
            this.rtuSize = rtuSize
            this.uri = uri
    }

    suspend fun show_down_data(str: String)
    {
        withContext(Dispatchers.Main) {
            globbal_calss.printf_to_tempinal(str)
        }
    }
}